package br.com.mrh.faces;

import java.io.IOException;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

/**
 * Classe utilizada de envio de mensagem para paginas JSF.<br>
 * Elimina a necessidade de chamar request/response/context/parameter no meio do
 * Bean poluindo o codigo.
 * 
 * @author GDS Solution
 * @since 10/05/2011
 * @version 1.0
 */
@Component
public class FacesUtil {

	/** Gravar os log's  */
	protected static Logger log = Logger.getLogger(Class.class);

	/**
	 * Metodo para obter o Parameter da Pagina
	 * 
	 * @return String
	 */
	public static String getRequestParameter(String name) {
		return (String) FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get(name);
	}

	/** */
	public static String getActionAttribute(ActionEvent event, String name) {
	        return (String) event.getComponent().getAttributes().get(name);
	    }

	/**
	 * Envio de Mensagem para pagina quando SUCESSO
	 * 
	 * @param mensagem
	 */
	public static void exibirMensagemSucesso(String mensagem, String componentName) {
		exibirMensagem(FacesMessage.SEVERITY_INFO, mensagem, componentName);
	}
	
	/**
	 * Envio de Mensagem para pagina quando ALERTA
	 * 
	 * @param mensagem
	 */
	public static void exibirMensagemAlerta(String mensagem) {
		exibirMensagem(FacesMessage.SEVERITY_WARN, mensagem, null);
	}
	
	/**
	 * Envio de Mensagem para pagina quando ALERTA
	 * 
	 * @param mensagem
	 */
	public static void exibirMensagemAlerta(String mensagem, String componentName) {
		exibirMensagem(FacesMessage.SEVERITY_WARN, mensagem, componentName);
	}

	/**
	 * Envio de Mensagem para pagina quando ERRO
	 * 
	 * @param mensagem
	 */
	public static void exibirMensagemErro(String mensagem, String componentName) {
		exibirMensagem(FacesMessage.SEVERITY_ERROR, mensagem, componentName);
	}
	
	/**
	 * Envio de Mensagem para pagina quando ERRO
	 * 
	 * @param mensagem
	 */
	public static void exibirMensagemErro(String mensagem) {
		exibirMensagem(FacesMessage.SEVERITY_ERROR, mensagem, null);
	}
	
	/**
	 * 
	 * @param severity
	 * @param mensagem
	 */
	private static void exibirMensagem(FacesMessage.Severity severity,	String mensagem, String componentName) {
		
		FacesMessage facesMessage = new FacesMessage(severity, mensagem, mensagem);
		FacesContext.getCurrentInstance().addMessage(componentName == null ? null : componentName.trim() , facesMessage);
	}	
	
	/**
	 * 
	 * @param message
	 */
	public static void exibirMensagem(String message){
		FacesMessage facesMessage = new FacesMessage(message);
		FacesContext.getCurrentInstance().addMessage( null, facesMessage );  
	}

	/**
	 * This class allows the Faces API to be unaware of the nature of its
	 * containing application environment. In particular, this class allows
	 * JavaServer Faces based appications to run in either a Servlet or a
	 * Portlet environment.
	 * 
	 * @return ExternalContext
	 * @link http://download.oracle.com/javaee/5/api/javax/faces/context/
	 *       ExternalContext.html
	 */
	public static ExternalContext getExternalContext() {
		return FacesContext.getCurrentInstance().getExternalContext();
	}
	
    /*
     * Faces Object Helpers
     */
    public static FacesContext getFacesContext(){
        return FacesContext.getCurrentInstance();
    }


	/**
	 * 
	 * @return Map
	 */
	@SuppressWarnings("rawtypes")
	public static Map getSessionMap() {
		return FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
	}

	/**
	 * Metodo para obter o Context da Pagina
	 * 
	 * @return ServletContext
	 */
	public static ServletContext getServletContext() {
		return (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
	}

	/**
	 * Metodo para obter o Response da Pagina
	 * 
	 * @return HttpServletRequest
	 */
	public static HttpServletRequest getServletRequest() {
		return (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
	}

	/**
	 * Metodo para obter o Request da Pagina
	 * 
	 * @return HttpServletResponse
	 */
	public static HttpServletResponse getServletResponse() {
		return (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
	}
	
	/*
     * Application Control Methods
     */

    public static void doForward(final String url){

        try{
            FacesContext context = getFacesContext();
            context.getExternalContext().dispatch(url);
        
        } catch (Exception e){
        	log.error("Erro no metodo doForward "+e);
        }
    }

    /**
     * Send a client HTTP redirect and halt further Faces Life-cycle processing
     */
    public static void doRedirect(final String url) {
        
    	try {
            
    		FacesContext context = getFacesContext();
            context.getExternalContext().redirect(url);
            context.responseComplete();
            
        }catch (IOException e){
            log.error("Erro no fazer o Redirect ",e);
        }
    }

    /**
     * 
     */
    public static void show404(){
    	    
        try {
        	
            FacesContext context = getFacesContext();
            HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            context.responseComplete();
        }
        catch (IOException e){
        	log.error("Erro ",e);
            throw new RuntimeException(e);
        }
    }
    
    /*
     * Application Helper Methods
     */
    public static String getContextRoot(){
        FacesContext facesContext = getFacesContext();
        return facesContext.getExternalContext().getRequestContextPath();
    }

    /**
     * 
     * @param component
     * @param fieldName
     * @return
     */
    public Object getFormValue(final UIComponent component, final String fieldName){
        String componentId = (String) component.getAttributes().get(fieldName);
        UIInput input = (UIInput) getFacesContext().getViewRoot().findComponent(componentId);
        return input.getValue();
    }

    /**
     * 
     * @param clientId
     * @return
     */
    public UIComponent getComponent(final String clientId){
    	
        FacesContext facesContext = getFacesContext();
        UIViewRoot viewRoot = facesContext.getViewRoot();
        UIComponent component = viewRoot.findComponent(clientId);
        if (component == null){
            component = findChildComponent(facesContext, viewRoot, clientId);
        }
        return component;
    }

    /**
     * 
     * @param facesContext
     * @param component
     * @param clientId
     * @return
     */
    private UIComponent findChildComponent(final FacesContext facesContext, final UIComponent component,
            final String clientId){

    	if (component == null || component.getChildCount() == 0){
            return null;
        }

        UIComponent result = null;
        for (UIComponent c : component.getChildren()){
            if (c.getClientId(facesContext).equals(clientId)){
                result = c;
                break;
            }else{
            	
                result = findChildComponent(facesContext, c, clientId);
                if (result != null && clientId.equals(result.getClientId(facesContext))){
                    break;
                }
            }
        }
        return result;
    }

    public static Object getManagedBean(String managedBean) {
    	FacesContext context = FacesContext.getCurrentInstance();
    	return context.getELContext().getELResolver().getValue(context.getELContext(), null, managedBean);
    }
}